import React, {
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useReducer,
  useRef,
  useState,
} from "react";
import { initialValue, reducer } from "../CommonFunctions";

import Child from "./Child";
import ChildCount from "./ChildCount";
import ChildNum from "./ChildNum";
import MyContext from "./Context";

export const useSelector = (selector) => {
  console.log("init useSelector");
  // 强制更新
  const [, forceRender] = useReducer((s) => s + 1, 0);
  const store = useContext(MyContext);

  // 获取当前使用的 state
  const selectedStateRef = useRef(null);
  selectedStateRef.current = selector(store.getState());

  // 对比更新回调
  const checkForUpdates = useCallback(() => {
    // 获取变更后的 state
    const newState = selector(store.getState());
    console.log("000", store.getState(), newState);
    // 对比前后两次 state
    if (newState !== selectedStateRef.current) forceRender({});
    console.log("checkForUpdates", selector);
  }, [store, selector]);

  // 订阅 state
  useEffect(() => {
    const subscription = store.subscribe(checkForUpdates);
    console.log("useEffect", subscription);
    return () => subscription();
  }, [store, checkForUpdates]);

  // 返回需要的 state
  return selectedStateRef.current;
};

export const useDispatch = () => {
  const store = useContext(MyContext);
  return store.dispatch;
};

const ProviderWarp = ({ children }) => {
  const [store, dispatch] = useReducer(reducer, initialValue);

  // ref state
  const storeRef = useRef(null);
  storeRef.current = store;

  // ref 订阅回调数组
  const subscribersRef = useRef([]);

  // state 变化，遍历执行回调
  useEffect(() => {
    subscribersRef.current.forEach((sub) => sub());
    console.log("state 变化，遍历执行回调");
  }, [store]);

  // 缓存 value， 利用 ref 拿到最新的 state, subscribe 状态
  const value = useMemo(
    () => ({
      dispatch,
      subscribe: (cb) => {
        subscribersRef.current.push(cb);
        return () => {
          subscribersRef.current = subscribersRef.current.filter((sub) => {
            return sub !== cb;
          });
        };
      },
      getState: () => storeRef.current,
    }),
    []
  );

  // return <MyContext.Provider children={children} value={value} />;
  return <MyContext.Provider value={value}>{children}</MyContext.Provider>;
};

const Demo3 = () => {
  const [isExtends, setIsExtends] = useState(false);
  return (
    <ProviderWarp>
      <div className="ProviderContainer BlueBorder">
        <div className="SectionHeader">
          <h3 className="SectionTitle">DEMO 3: 观察者模式, 实现按需渲染</h3>
          <h3
            className={`SectionAction ${isExtends ? "" : "ArrowDown"}`}
            onClick={() => setIsExtends(!isExtends)}
          >
            {">"}
          </h3>
        </div>
        {isExtends ? (
          <>
            <ChildCount />
            <ChildNum />
            <Child />
          </>
        ) : null}
      </div>
    </ProviderWarp>
  );
};
export default Demo3;
